﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;
using System.Web;
using System.Web.Caching;

namespace NetDh.Cache
{
    /*
     * 如果你的缓存介质会有切换的可能，则建议用接口操作，
     * 此内存缓存操作类RuntimeCacheHandle是使用现成的System.Web.HttpRuntime实现，B/S、C/S都可以使用。
     */

    /// <summary>
    /// 内存缓存操作类。
    /// </summary>
    public class RuntimeCacheHandle : ICacheHandle
    {
        /// <summary>
        /// 取缓存。
        /// </summary>
        /// <typeparam name="T">T可以是引用类型，也可以是值类型</typeparam>
        /// <param name="key"></param>
        /// <returns>当缓存不存在时，引用类型返回null；而值类型返回的默认值，并不代表缓存存在。</returns>
        public T Get<T>(string key)
        {
            object value = HttpRuntime.Cache.Get(key);
            if (value != null)
            {
                return (T)value;
            }
            return default(T);//注意:值类型返回的默认值 ，并不代表缓存存在。
        }

        /// <summary>
        /// 存入缓存。存入的是源value数据的备份，源数据修改不影响缓存。
        /// (一般直接写Set("key1",obj)，而不用Set<object>("key1",obj)，因为.net会自动根据obj判断T的类型)
        /// </summary>
        /// <typeparam name="T">T可以是引用类型，也可以是值类型</typeparam>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <param name="timeOut">缓存的过期时间(秒)，-1代表不过期。</param>
        /// <returns></returns>
        public bool Set<T>(string key, T value, int timeOut = -1)
        {
            if (timeOut == -1)
            {
                HttpRuntime.Cache.Insert(key, value);
            }
            else
            {
                var timeSpan = new TimeSpan(0, 0, timeOut);
                HttpRuntime.Cache.Insert(key, value, null, System.Web.Caching.Cache.NoAbsoluteExpiration, timeSpan);
            }
            return true;
        }

        /// <summary>
        /// 如果不存在key缓存，则添加，返回true。如果已经存在key缓存，则不作操作，返回false。
        /// (存入的是源value数据的备份，源数据修改不影响缓存。)
        /// </summary>
        /// <typeparam name="T">T可以是引用类型，也可以是值类型</typeparam>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <param name="timeOut">缓存的过期时间(秒)，-1代表不过期。</param>
        /// <returns></returns>
        public bool AddIfNotExist<T>(string key, T value, int timeOut = -1)
        {
            var timeSpan = timeOut > 0 ? new TimeSpan(0, 0, timeOut) : System.Web.Caching.Cache.NoSlidingExpiration;
            var oldCache = HttpRuntime.Cache.Add(key, value, null, System.Web.Caching.Cache.NoAbsoluteExpiration, timeSpan, CacheItemPriority.Normal, null);
            return oldCache == null;
        }

        /// <summary>
        /// 删除缓存
        /// </summary>
        /// <param name="key"></param>
        public void Remove(string key)
        {
            HttpRuntime.Cache.Remove(key);
        }

        public List<T> GetList<T>(List<string> keys)
        {
            //内存缓存不实现此接口函数，直接多次使用Get函数。
            //memcache/redis一般会实现此接口函数，是为了一次连接可取回多个值。
            throw new NotImplementedException();
        }
    }
}
